/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: worker.hpp
 */

#ifndef _WORKER_HPP_
#define _WORKER_HPP_

#include <iostream>
#include <string>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>

#include "runner.hpp"
#include "worker_descriptor.hpp"
#include "task_descriptor.hpp"
#include "tqueue_manager.hpp"
#include "common_types.hpp"
#include "synlogger.hpp"

//-----------------------------------------------------------------------------
// Enum, struct, aliases
namespace middleware {
typedef struct {
	std::string log_postfix; /* Postfix for logger */
} WConfig;
}
//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Period of time to check worker conditions and, if something changed, send
 * this new status to other peers.
 */
const unsigned int kWorkerStatusManagerRefreshPeriodMsec = 5000;
/*!
 * Etiquette for output.
 */
const std::string kWorkerEtq = "W:         ";
const std::string kWorker1Etq = "StatusManager:             ";
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
/*!
 * Class describing a worker.
 */
class Worker : public Runner {
	/*!
	 * To let the proxy operate correctly.
	 */
	friend class TQueueManagerProxy;
public:
	/*!
	 * Default constructor. Set to specified capabilities. A descriptor must
	 * be provided in order to provide address and capabilities. The address
	 * refers to a control bound loop on Manager that redirects tasks here.
	 */
	Worker(PeersKnowledge PK, WorkerDescriptor descriptor);
	/*!
	 * Providing logging too.
	 */
	Worker(WConfig conf, PeersKnowledge PK, WorkerDescriptor descriptor);
	/*!
	 * Destructor.
	 */
	~Worker();
	/*!
	 * Runs Worker. If another thread was running, it will be destoyed.
	 */
	void run() {
		this->_worker_thread.reset();
		this->_worker_thread = boost::shared_ptr<boost::thread>(
				new boost::thread(
						boost::bind(&Worker::exec, this)));
	}
	/*!
	 * Join this thread and wait for it to finish.
	 */
	void join() {
		(this->_worker_thread)->join();
	}
private:
	/*!
	 * Execution function.
	 */
	void exec();
	/*!
	 * Enqueues tasks when asked by Manager.
	 */
	void enqueuer(const TaskDescriptor& td);
	/*!
	 * Execution function for worker status manager.
	 */
	void exec_workerstatus_manager();
	/*!
	 * Manages a task when arriving ==> Executing it.
	 */
	void ManageTask(TaskDescriptor task);
	/*!
	 * Initialization routine with user.
	 */
	void bonjour();
	/*!
	 * Capabilities and other info about this worker.
	 */
	WorkerDescriptor _worker_descriptor;
	/*!
	 * Undrlaying thread. Responsible for dequeueing and executing tasks.
	 */
	boost::shared_ptr<boost::thread> _worker_thread;
	/*!
	 * Undrlaying thread. Responsible for sending worker status to discovery.
	 */
	boost::shared_ptr<boost::thread> _workerstatus_manager_thread;
	/*!
	 * Queue of tasks.
	 */
	TQueueManager _tqueue_manager;
	/*!
	 * Knowledge of neighboorhood.
	 */
	PeersKnowledge _pk;
	/*!
	 * Configuration.
	 */
	WConfig _config;
	/*!
	 * SynLogger.
	 */
	SynLogger _logger;
};
} /* middleware */

#endif
